﻿using Microsoft.EntityFrameworkCore;
using RemoteTool.Common;
using RemoteTool.Data.DtoModel;
using RemoteTool.Shared;
using System.Linq.Expressions;
using System.Text;

namespace RemoteTool.Data.Repository
{
    public class BaseService<T> : IBaseService<T> where T : class, new()
    {
       
        private readonly DbContext dbContext;

        public BaseService(DbContext dbContext)
        {
            this.dbContext = dbContext;
        }
        #region 添加操作
        /// <summary>
        /// 添加一条数据
        /// </summary>
        /// <param name="parm">T</param>
        /// <returns></returns>
        public async Task<ApiResult<string>> AddAsync(T parm, bool Async = true)
        {
            var res = new ApiResult<string>() { statusCode = (int)ApiEnum.Error };
            try
            {
                var dbres = Async? await dbContext.AddAsync<T>(parm): dbContext.Add<T>(parm);
                dbContext.SaveChanges();
                res.data = dbres.ToString();
                res.statusCode = (int)ApiEnum.Status;
            }
            catch (Exception ex)
            {
                res.message = ApiEnum.Error.GetEnumText() + ex.Message;
                Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
            }
            return res;
        }

        /// <summary>
        /// 批量添加数据
        /// </summary>
        /// <param name="parm">List<T></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> AddListAsync(List<T> parm, bool Async = true)
        {
            var res = new ApiResult<string>() { statusCode = (int)ApiEnum.Error };
            try
            {
                var sb = new StringBuilder();
                foreach (var item in parm)
                {
                    var dbres = Async ? await dbContext.AddAsync<T>(item) : dbContext.Add<T>(item);
                    sb.Append(dbres.ToString() + "|");
                }
                dbContext.SaveChanges();
                res.data = sb.ToString();
                res.statusCode = (int)ApiEnum.Status;
            }
            catch (Exception ex)
            {
                res.message = ApiEnum.Error.GetEnumText() + ex.Message;
                Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
            }
            return res;
        }
        #endregion

        #region 查询操作
        /// <summary>
        /// 获得一条数据
        /// </summary>
        /// <param name="where">Expression<Func<T, bool>></param>
        /// <returns></returns>
        public async Task<ApiResult<T>> GetModelAsync(Expression<Func<T, bool>> where, bool Async = true)
        {
            var res = new ApiResult<T>
            {
                statusCode = 200,
                data = Async ? await dbContext.Set<T>().Where(where).FirstAsync()??new T() { }
                : dbContext.Set<T>().Where(where).First()??new T() { }
            };
            return res;
        }

        /// <summary>
        /// 获得一条数据
        /// </summary>
        /// <param name="parm">string</param>
        /// <returns></returns>
        public async Task<ApiResult<T>> GetModelAsync(string parm, bool Async = true)
        {
            var res = new ApiResult<T>
            {
                statusCode = 200,
                data = Async ? await dbContext.Set<T>().FromSqlRaw<T>(parm).FirstAsync() ?? new T() { }
                : dbContext.Set<T>().FromSqlRaw<T>(parm).First() ?? new T() { }
            };
            return res;
        }

        /// <summary>
		/// 获得列表——分页
		/// </summary>
		/// <param name="parm">PageParm</param>
		/// <returns></returns>
        public async Task<ApiResult<Page<T>>> GetPagesAsync(PageParm parm, bool Async = true)
        {
            var res = new ApiResult<Page<T>>();
            try
            {

                var list = Async ? await dbContext.Set<T>().Skip((parm.page - 1) * parm.limit).Take(parm.limit).ToListAsync() :
                        dbContext.Set<T>().Skip((parm.page - 1) * parm.limit).Take(parm.limit).ToList();
                res.data = new Page<T>() { 
                    CurrentPage=parm.page,
                    ItemsPerPage=parm.limit,
                    Items=list
                };
            }
            catch (Exception ex)
            {
                res.message = ApiEnum.Error.GetEnumText() + ex.Message;
                res.statusCode = (int)ApiEnum.Error;
                Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
            }
            return res;
        }

        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="parm">分页参数</param>
        /// <param name="where">条件</param>
        /// <param name="order">排序值</param>
        /// <param name="orderEnum">排序方式OrderByType</param>
        /// <returns></returns>
        public async Task<ApiResult<Page<T>>> GetPagesAsync(PageParm parm, Expression<Func<T, bool>> where,
            Expression<Func<T, object>> order, DbOrderEnum orderEnum, bool Async = true)
        {
            var res = new ApiResult<Page<T>>();
            try
            {
                var query = (int)orderEnum == 1 ? dbContext.Set<T>().OrderBy(order) : dbContext.Set<T>().OrderByDescending(order);

                var list = Async ? await query.Skip((parm.page - 1) * parm.limit).Take(parm.limit).ToListAsync() :
                        query.Skip((parm.page - 1) * parm.limit).Take(parm.limit).ToList();
                res.data = new Page<T>()
                {
                    CurrentPage = parm.page,
                    ItemsPerPage = parm.limit,
                    Items = list
                };
            }
            catch (Exception ex)
            {
                res.message = ApiEnum.Error.GetEnumText() + ex.Message;
                res.statusCode = (int)ApiEnum.Error;
                Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
            }
            return res;
        }

        /// <summary>
		/// 获得列表
		/// </summary>
		/// <param name="parm">PageParm</param>
		/// <returns></returns>
        public async Task<ApiResult<List<T>>> GetListAsync(Expression<Func<T, bool>> where,
            Expression<Func<T, object>> order, DbOrderEnum orderEnum, bool Async = true)
        {
            var res = new ApiResult<List<T>>();
            try
            {
                var query = (int)orderEnum == 1 ? dbContext.Set<T>().OrderBy(order) : dbContext.Set<T>().OrderByDescending(order);

                res.data = Async ? await query.ToListAsync() : query.ToList();
            }
            catch (Exception ex)
            {
                res.message = ApiEnum.Error.GetEnumText() + ex.Message;
                res.statusCode = (int)ApiEnum.Error;
                Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
            }
            return res;
        }

        /// <summary>
        /// 获得列表，不需要任何条件
        /// </summary>
        /// <returns></returns>
        public async Task<ApiResult<List<T>>> GetListAsync(bool Async = true)
        {
            var res = new ApiResult<List<T>>();
            try
            {
                res.data = Async ? await dbContext.Set<T>().ToListAsync() : dbContext.Set<T>().ToList();
            }
            catch (Exception ex)
            {
                res.message = ApiEnum.Error.GetEnumText() + ex.Message;
                res.statusCode = (int)ApiEnum.Error;
                Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
            }
            return res;
        }
        #endregion

        #region 修改操作
        /// <summary>
        /// 修改一条数据
        /// </summary>
        /// <param name="parm">T</param>
        /// <returns></returns>
        public async Task<ApiResult<string>> UpdateAsync(T parm, bool Async = true)
        {
            var res = new ApiResult<string>() { statusCode = (int)ApiEnum.Error };
            try
            {
                dbContext.Set<T>().Update(parm);
                var dbres = Async ? await dbContext.SaveChangesAsync() : dbContext.SaveChanges();
                //var dbres= Async? await Db.Updateable<T>(parm).ExecuteCommandAsync() : Db.Updateable<T>(parm).ExecuteCommand();
                res.data= dbres.ToString();
                res.statusCode = (int)ApiEnum.Status;
            }
            catch (Exception ex)
            {
                res.message = ApiEnum.Error.GetEnumText() + ex.Message;
                Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
            }
            return res;
        }

        /// <summary>
        /// 批量修改
        /// </summary>
        /// <param name="parm">T</param>
        /// <returns></returns>
        public async Task<ApiResult<string>> UpdateAsync(List<T> parm, bool Async = true)
        {
            var res = new ApiResult<string>() { statusCode = (int)ApiEnum.Error };
            try
            {
                dbContext.Set<T>().UpdateRange(parm);
                var dbres = Async ? await dbContext.SaveChangesAsync() : dbContext.SaveChanges();
                //var dbres = Async? await Db.Updateable<T>(parm).ExecuteCommandAsync() : Db.Updateable<T>(parm).ExecuteCommand();
                //res.data = dbres.ToString();
                res.statusCode = (int)ApiEnum.Status;
            }
            catch (Exception ex)
            {
                res.message = ApiEnum.Error.GetEnumText() + ex.Message;
                Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
            }
            return res;
        }

        /// <summary>
        /// 修改一条数据，可用作假删除
        /// </summary>
        /// <param name="columns">修改的列=Expression<Func<T,T>></param>
        /// <param name="where">Expression<Func<T,bool>></param>
        /// <returns></returns>
        //public async Task<ApiResult<string>> UpdateAsync(Expression<Func<T, T>> columns,
        //    Expression<Func<T, bool>> where, bool Async = true)
        //{
        //    var res = new ApiResult<string>() { statusCode = (int)ApiEnum.Error };
        //    try
        //    {
        //        var dbres = Async ? await Db.Updateable<T>().SetColumns(columns).Where(where).ExecuteCommandAsync() 
        //            : Db.Updateable<T>().SetColumns(columns).Where(where).ExecuteCommand();
        //        res.data = dbres.ToString();
        //        res.statusCode = (int)ApiEnum.Status;
        //    }
        //    catch (Exception ex)
        //    {
        //        res.message = ApiEnum.Error.GetEnumText() + ex.Message;
        //        Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
        //    }
        //    return res;
        //}
        #endregion

        #region 删除操作
        /// <summary>
        /// 删除一条或多条数据
        /// </summary>
        /// <param name="parm">string</param>
        /// <returns></returns>
        //public async Task<ApiResult<string>> DeleteAsync(string parm, bool Async = true)
        //{
        //    var res = new ApiResult<string>() { statusCode = (int)ApiEnum.Error };
        //    try
        //    {  
        //        var list = Utils.StrToListString(parm);
        //        var dbres = Async ? await Db.Deleteable<T>().In(list.ToArray()).ExecuteCommandAsync() : Db.Deleteable<T>().In(list.ToArray()).ExecuteCommand();
        //        res.data = dbres.ToString();
        //        res.statusCode = (int)ApiEnum.Status;
        //    }
        //    catch (Exception ex)
        //    {
        //        res.message = ApiEnum.Error.GetEnumText() + ex.Message;
        //        Logger.Default.ProcessError((int)ApiEnum.Error,ex.Message);
        //    }
        //    return res;
        //}

        /// <summary>
        /// 删除一条或多条数据
        /// </summary>
        /// <param name="where">Expression<Func<T, bool>></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> DeleteAsync(Expression<Func<T, bool>> where, bool Async = true)
        {
            var res = new ApiResult<string>() { statusCode = (int)ApiEnum.Error };
            try
            {
                var list = Async ? await dbContext.Set<T>().Where(where).ToListAsync() : dbContext.Set<T>().Where(where).ToList();
                dbContext.Set<T>().RemoveRange(list);
                var dbres = Async ? await dbContext.SaveChangesAsync() : dbContext.SaveChanges();
                //var dbres = Async? await Db.Deleteable<T>().Where(where).ExecuteCommandAsync() : Db.Deleteable<T>().Where(where).ExecuteCommand();
                res.data = dbres.ToString();
                res.statusCode = (int)ApiEnum.Status;
            }
            catch (Exception ex)
            {
                res.message = ApiEnum.Error.GetEnumText() + ex.Message;
                Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
            }
            return res;
        }
        #endregion

        #region 查询Count
        public async Task<ApiResult<ResultCount>> CountAsync(Expression<Func<T, bool>> where, bool Async = true)
        {
            var res = new ApiResult<ResultCount>() { statusCode = (int)ApiEnum.Error };
            try
            {
                var list = Async ? await dbContext.Set<T>().Where(where).ToListAsync() : dbContext.Set<T>().Where(where).ToList();
                res.data = new ResultCount
                {
                    Count = list.Count,
                };
                res.statusCode = (int)ApiEnum.Status;
            }
            catch (Exception ex)
            {
                res.message = ApiEnum.Error.GetEnumText() + ex.Message;
                Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
            }
            return res;
        }
        #endregion

        #region 是否存在
        public async Task<ApiResult<ResultAny>> IsExistAsync(Expression<Func<T, bool>> where, bool Async = true)
        {
            var res = new ApiResult<ResultAny>() { statusCode = (int)ApiEnum.Error };
            try
            {
                res.data = new ResultAny
                {
                    Any = Async ? await dbContext.Set<T>().Where(where).AnyAsync() : dbContext.Set<T>().Where(where).Any()
                };
                res.statusCode = (int)ApiEnum.Status;
            }
            catch (Exception ex)
            {
                res.message = ApiEnum.Error.GetEnumText() + ex.Message;
                Logger.Default.ProcessError((int)ApiEnum.Error, ex.Message);
            }
            return res;
        }
        #endregion
    }
}
